#include "pending_data_queue.h"
#include "semUntil.h"
#include "CxlUtil.h"

// 图片上送数据队列，低优先级队列
static PacketQueue pepicsQueue;

void picsQueueInit()
{
    pepicsQueue.bot = NULL;
    pepicsQueue.top = NULL;
    pepicsQueue.len = 0;
    pthread_mutex_init(&pepicsQueue.lock, NULL);
}

bool isPicsQueueEmpty()
{
    pthread_mutex_lock(&pepicsQueue.lock);
    bool isEmpty = PacketIsEmpty(&pepicsQueue);
    pthread_mutex_unlock(&pepicsQueue.lock);

    return isEmpty;
}

void picsEnqueue(Packet *p)
{
    pthread_mutex_lock(&pepicsQueue.lock);
    PacketEnqueue(&pepicsQueue, p);
    pthread_mutex_unlock(&pepicsQueue.lock);
}

Packet *picsDequeue()
{
    pthread_mutex_lock(&pepicsQueue.lock);
    Packet *tmp = PacketDequeue(&pepicsQueue);
    pthread_mutex_unlock(&pepicsQueue.lock);
    return tmp;
}

uint32_t getPicsQueueLen()
{
    uint32_t len = 0;
    pthread_mutex_lock(&pepicsQueue.lock);
    len = pepicsQueue.len;
    pthread_mutex_unlock(&pepicsQueue.lock);
    return len;
}

// 其他上送数据队列，如标定结果等属于非主线程需要上送的数据，高优先级队列
static PacketQueue othersQueue;

void othersQueueInit()
{
    othersQueue.bot = NULL;
    othersQueue.top = NULL;
    othersQueue.len = 0;
    pthread_mutex_init(&othersQueue.lock, NULL);
}

bool isOthersQueueEmpty()
{
    pthread_mutex_lock(&othersQueue.lock);
    bool isEmpty = PacketIsEmpty(&othersQueue);
    pthread_mutex_unlock(&othersQueue.lock);

    return isEmpty;
}

void othersEnqueue(Packet *p)
{
    pthread_mutex_lock(&othersQueue.lock);
    PacketEnqueue(&othersQueue, p);
    pthread_mutex_unlock(&othersQueue.lock);
}

Packet *othersDequeue()
{
    pthread_mutex_lock(&othersQueue.lock);
    Packet *tmp = PacketDequeue(&othersQueue);
    pthread_mutex_unlock(&othersQueue.lock);
    return tmp;
}

uint32_t getOthersQueueLen()
{
    uint32_t len = 0;
    pthread_mutex_lock(&othersQueue.lock);
    len = othersQueue.len;
    pthread_mutex_unlock(&othersQueue.lock);
    return len;
}

// sql执行命令队列
static PacketQueue sqlCmdQueue;

void sqlCmdQueueInit()
{
    sqlCmdQueue.bot = NULL;
    sqlCmdQueue.top = NULL;
    sqlCmdQueue.len = 0;
    pthread_mutex_init(&sqlCmdQueue.lock, NULL);
}

bool isSqlCmdQueueEmpty()
{
    pthread_mutex_lock(&sqlCmdQueue.lock);
    bool isEmpty = PacketIsEmpty(&sqlCmdQueue);
    pthread_mutex_unlock(&sqlCmdQueue.lock);

    return isEmpty;
}

void sqlEnqueue(Packet *p)
{
    pthread_mutex_lock(&sqlCmdQueue.lock);
    PacketEnqueue(&sqlCmdQueue, p);
    pthread_mutex_unlock(&sqlCmdQueue.lock);
}

Packet *sqlDequeue()
{
    pthread_mutex_lock(&sqlCmdQueue.lock);
    Packet *tmp = PacketDequeue(&sqlCmdQueue);
    pthread_mutex_unlock(&sqlCmdQueue.lock);
    return tmp;
}

uint32_t getSqlQueueLen()
{
    uint32_t len = 0;
    pthread_mutex_lock(&sqlCmdQueue.lock);
    len = sqlCmdQueue.len;
    pthread_mutex_unlock(&sqlCmdQueue.lock);
    return len;
}

// sql查询出来的图片送socket的队列
static PacketQueue sql2SocketQueue;
void sql2SocketQueueInit()
{
    sql2SocketQueue.bot = NULL;
    sql2SocketQueue.top = NULL;
    sql2SocketQueue.len = 0;
    pthread_mutex_init(&sql2SocketQueue.lock, NULL);
}

bool isSql2SocketEmpty()
{
    pthread_mutex_lock(&sql2SocketQueue.lock);
    bool isEmpty = PacketIsEmpty(&sql2SocketQueue);
    pthread_mutex_unlock(&sql2SocketQueue.lock);

    return isEmpty;
}

void sql2SocketEnqueue(Packet *p)
{
    pthread_mutex_lock(&sql2SocketQueue.lock);
    PacketEnqueue(&sql2SocketQueue, p);
    pthread_mutex_unlock(&sql2SocketQueue.lock);
}

Packet *sql2SocketDequeue()
{
    pthread_mutex_lock(&sql2SocketQueue.lock);
    Packet *tmp = PacketDequeue(&sql2SocketQueue);
    pthread_mutex_unlock(&sql2SocketQueue.lock);
    return tmp;
}

// 处理图片上送和响应的队列，跟上俩队列不是一个概念
// static PacketQueue vzWrokReqQueue;

// void vzWrokReqQueueInit()
// {
//     vzWrokReqQueue.bot = NULL;
//     vzWrokReqQueue.top = NULL;
//     vzWrokReqQueue.len = 0;
//     pthread_mutex_init(&vzWrokReqQueue.lock, NULL);
// }

// bool isVzWrokReqQueueEmpty()
// {
//     pthread_mutex_lock(&vzWrokReqQueue.lock);
//     bool isEmpty = PacketIsEmpty(&vzWrokReqQueue);
//     pthread_mutex_unlock(&vzWrokReqQueue.lock);

//     return isEmpty;
// }

// void vzWrokReqEnqueue(Packet *p)
// {
//     pthread_mutex_lock(&vzWrokReqQueue.lock);
//     PacketEnqueue(&vzWrokReqQueue, p);
//     // vz_work_req_t *pp = (vz_work_req_t *)p->pkt_data;
//     // LOG_INFO("[文件id %d]通知结构入队，对应定时器地址%p", pp->fileCode, pp->timer);
//     pthread_mutex_unlock(&vzWrokReqQueue.lock);
// }

// void fireEventVzWorkByFileId(uint16_t fileId)
// {
//     Packet *tmp = NULL;
//     vz_work_req_t *req_t = NULL;
//     pthread_mutex_lock(&vzWrokReqQueue.lock);
//     for (size_t i = 0; i < vzWrokReqQueue.len; i++)
//     {
//         tmp = PacketDequeue(&vzWrokReqQueue);
//         req_t = (vz_work_req_t *)tmp->pkt_data;
//         if (req_t->fileCode == fileId)
//         {
//             req_t->isRecvRespon = true;
//             // LOG_INFO("[文件id %d]通知结构触发信号量，对应定时器地址%p", req_t->fileCode, req_t->timer);
//             // 五次发包
//             for (size_t i = 0; i < 5; i++)
//             {
//                 semPostAndPerror(&req_t->sem);
//             }
//         }
//         PacketEnqueue(&vzWrokReqQueue, tmp);
//     }
//     pthread_mutex_unlock(&vzWrokReqQueue.lock);
// }

// void dequeueVzWorkByFileId(uint16_t fileId)
// {
//     Packet *tmp = NULL;
//     vz_work_req_t *req_t = NULL;
//     pthread_mutex_lock(&vzWrokReqQueue.lock);
//     for (size_t i = 0; i < vzWrokReqQueue.len; i++)
//     {
//         tmp = PacketDequeue(&vzWrokReqQueue);
//         req_t = (vz_work_req_t *)tmp->pkt_data;
//         if (req_t->fileCode == fileId)
//         {
//             // LOG_INFO("[文件id %d]通知结构触发信号量，对应定时器地址%p", req_t->fileCode, req_t->timer);
//             free(tmp);
//             break;
//         }
//         else
//         {
//             PacketEnqueue(&vzWrokReqQueue, tmp);
//         }
//     }
//     pthread_mutex_unlock(&vzWrokReqQueue.lock);
// }

// TODO: 目前未稳定，要测试
// 定时器队列，需要的从这里取去用，不需要的时候归还队列里
#define INIT_TIMER_NUMS 20
#define EXTEND_TIMER_NUMS 5
#define DELTA_TO_EXTEND 3
static void extendTimerQueue(uint8_t num);

typedef struct
{
    uv_timer_t timer;
    bool isUsed;
} UvTimerStruct;

static PacketQueue timerQueue;

void timerQueueInit()
{
    timerQueue.bot = NULL;
    timerQueue.top = NULL;
    timerQueue.len = 0;
    pthread_mutex_init(&timerQueue.lock, NULL);
    extendTimerQueue(INIT_TIMER_NUMS);
}

static void extendTimerQueue(uint8_t num)
{
    UvTimerStruct *uvTimerArr = (UvTimerStruct *)malloc(sizeof(UvTimerStruct) * num);
    for (size_t i = 0; i < EXTEND_TIMER_NUMS; i++)
    {
        uv_timer_init(getLoop(), &uvTimerArr[i].timer);
        uvTimerArr[i].isUsed = false;
        Packet *packTmp = (Packet *)malloc(sizeof(Packet));
        packTmp->pkt_data = (uint8_t *)&uvTimerArr[i];
        PacketEnqueue(&timerQueue, packTmp);
    }
}

static uv_timer_t *getTimerCanUse(uint16_t *traversalLen)
{
    Packet *packTmp = timerQueue.bot;
    UvTimerStruct *uvTimer = NULL;
    if (traversalLen != NULL)
    {
        *traversalLen = 0;
    }
    else
    {
        return NULL;
    }
    while (packTmp != NULL)
    {
        (*traversalLen)++;
        uvTimer = (UvTimerStruct *)packTmp->pkt_data;
        if (uvTimer->isUsed == false)
        {
            uvTimer->isUsed = true;
            break;
        }
        packTmp = packTmp->prev;
    }
    return &uvTimer->timer;
}

uv_timer_t *timerDequeue()
{
    uv_timer_t *timer = NULL;
    pthread_mutex_lock(&timerQueue.lock);
    uint16_t traversalLen = 0;
    timer = getTimerCanUse(&traversalLen);

    if (traversalLen > (timerQueue.len - DELTA_TO_EXTEND))
    {
        extendTimerQueue(EXTEND_TIMER_NUMS);
    }

    pthread_mutex_unlock(&timerQueue.lock);
    // LOG_INFO("[文件id %d]使用的定时器地址%p", fileId, timer);
    // LOG_INFO("返回的定时器地址%p", timer);
    return timer;
}

void timerEnqueue(uv_timer_t *timer)
{
    pthread_mutex_lock(&timerQueue.lock);

    Packet *packTmp = timerQueue.bot;
    UvTimerStruct *uvTimer = NULL;
    while (packTmp != NULL)
    {
        uvTimer = (UvTimerStruct *)packTmp->pkt_data;
        if (uvTimer->isUsed == true)
        {
            if (timer == &uvTimer->timer)
            {

                uvTimer->isUsed = false;
                // LOG_INFO("[文件id %d]返还的定时器地址%p", fileId, timer);
                break;
            }
        }
        packTmp = packTmp->prev;
    }

    pthread_mutex_unlock(&timerQueue.lock);
}